package ac.svn.accesscontrol.controller;

import java.io.File;
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;

import ac.notification.event.INotificationListener;
import ac.notification.event.NotificationEvent;
import ac.notification.manager.NotificationRegistrar;
import ac.svn.accesscontrol.manager.SVNInfoManager;
import ac.svn.accesscontrol.store.AccessFile;
import ac.svn.accesscontrol.store.AccessUnit;
import ac.svn.accesscontrol.store.Dictionary;
import ac.svn.accesscontrol.store.ISVNIdentifier;
import ac.svn.accesscontrol.store.ISVNItem;
import ac.svn.accesscontrol.store.SVNGroup;
import ac.svn.accesscontrol.store.SVNLocation;

public class AccessFileWriter implements INotificationListener ,ISVNIdentifier
{
	private JFileChooser chooser;
	public AccessFileWriter()
	{
		chooser = new JFileChooser();
		chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
		chooser.setMultiSelectionEnabled(false);

		NotificationRegistrar.registerListener(this);

	}

	@Override
	public void receiveEvent(NotificationEvent notificationEvent) 
	{
		if(notificationEvent.getPropertyIdentifier().equals(CMD_SAVE_FILE))
		{
			SwingUtilities.invokeLater(new Runnable() 
			{
				@Override
				public void run() 
				{
					saveAccessFile(false);
				}
			}); 
		}
		else if(notificationEvent.getPropertyIdentifier().equals(CMD_SAVE_FILE_AS))
		{
			SwingUtilities.invokeLater(new Runnable() 
			{
				@Override
				public void run() 
				{
					saveAccessFile(true);
				}
			}); 
		}
	}

	private void saveAccessFile(boolean saveAs) 
	{
		String fileName = getFileName(saveAs);

		//Check if at all file has been ever opened.
		if(null != fileName)
		{
			try
			{
				File file = new File(fileName);
				FileWriter fileWriter = new FileWriter(file);

				//Generate Contents
				String contents = generateContents();

				fileWriter.write(contents);

				fileWriter.close();				
			}
			catch(final Exception fe)
			{
				fe.printStackTrace();
				String message = String.format("Unable to save file due to reason:%s", fe.getMessage());
				JOptionPane.showMessageDialog(null, message,"Save failed!",JOptionPane.ERROR_MESSAGE);
			}
		}

	}

	private String getFileName(boolean saveAs)
	{
		String filePath = null;

		if(true == saveAs)
		{
			int selOption = chooser.showSaveDialog(null);
			if(JFileChooser.APPROVE_OPTION == selOption)
			{
				String fileName = chooser.getSelectedFile().getName().trim();
				if((null == fileName )||(true == fileName.isEmpty()))
				{
					JOptionPane.showMessageDialog(null, "No Selection made!","Error",JOptionPane.ERROR_MESSAGE);
				}
				else
				{
					filePath = chooser.getSelectedFile().getAbsolutePath();
				}
			}
			else
			{
				JOptionPane.showMessageDialog(null, "No Selection made!","Error",JOptionPane.ERROR_MESSAGE);
			}
		}
		else
		{
			AccessFile  accessFile = Dictionary.getDictionary().getLastAccessFile();
			//Check if at all file has been ever opened.
			if(null == accessFile)
			{
				filePath = getFileName(false);
			}
			else
			{
				filePath = accessFile.getAccessFileLocation();
			}
		}

		return filePath;
	}




	private String generateContents()
	{
		//Get SVNInformanager.
		SVNInfoManager  svnInfMgr = SVNInfoManager.getInfoManager();

		//Buffer for final file
		StringBuffer stringBuffer = new StringBuffer();

		//Generate contents.
		stringBuffer.append("#Generated on " + (new Date()).toString() + "\n");
		stringBuffer.append("[groups]\n");

		List<SVNGroup> allGroups = new ArrayList<SVNGroup>();
		
		for(ISVNItem item : svnInfMgr.getAllGroups())
		{
			SVNGroup  svnGroup = (SVNGroup) item;
			allGroups.add(svnGroup);
		}
		 
		//Sort By group name
		Collections	.sort(allGroups);
		
		for(SVNGroup svnGroup : allGroups)
		{
			String groupTag = "";

			String header = svnGroup.getComments();
					
			String userList = svnGroup.getGroupMembers().toString();
			userList = userList.replace("["," ");
			userList = userList.replace("]"," ");
			userList = userList.trim();


			if((null != header) && (false == header.trim().isEmpty()))
			{
				//Make sure new line is added after comment.
				if(false == header.endsWith("\n"))
				{
					header+="\n";
				}
				groupTag = String.format("\n%s%s=%s\n",header,svnGroup.getGroupAlias(),userList);
			}
			else
			{
				groupTag = String.format("%s=%s\n",svnGroup.getGroupName(),userList);
			}
			stringBuffer.append(groupTag);
		}

		stringBuffer.append("\n\n");

		for(ISVNItem item : svnInfMgr.getAllLocations())
		{
			SVNLocation svnLocation = (SVNLocation) item;
			String locationHeader = svnLocation.getComments();
			
			if(null == locationHeader)
			{
				locationHeader = "";
			}
			
			StringBuffer locationTag = new StringBuffer(String.format("%s[%s]\n",locationHeader,svnLocation.getLocationPath()));
			for(String  accessUnitId : svnLocation.getAccessUnits())
			{
				AccessUnit accessUnit = svnInfMgr.getAccessUnit(accessUnitId);
				String header = accessUnit.getComments();

				if(null == header)
				{
					header = "";
				}
		
				String prefix = "";
				if(svnInfMgr.isAGroup(accessUnit.getOwnerId()))
				{
					prefix = "@";
				}

				String strAccessUnit = String.format("%s%s%s = %s\n",header,prefix,accessUnit.getOwnerId(),accessUnit.getAccessAsString());
				locationTag.append(strAccessUnit);									
			}
			stringBuffer.append(locationTag + "\n");
		}

		return stringBuffer.toString();
	}

	@Override
	public Set<String> declaredSubscriptionSet() 
	{
		Set<String> subscriptions = new HashSet<String>();
		subscriptions.add(CMD_SAVE_FILE);
		subscriptions.add(CMD_SAVE_FILE_AS);
		return subscriptions;
	}

}
